package com.xingge.sdktest.convert;

import android.content.Context;
import android.os.Environment;
import android.text.TextUtils;

import com.jolimark.UsbTool;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import dalvik.system.PathClassLoader;

public class PrintConverter {

    private static final String STOR_PATH = Environment.getExternalStorageDirectory().getAbsolutePath();
    private static final String FILE_NAME = "pngfile";
    private Context context;
    private static String nativePath;

    public PrintConverter(Context context) {
        this.context = context;
        nativePath = getNativePath(context);
    }

    public static String getNativePath(Context context) {
        if (TextUtils.isEmpty(nativePath)) {
            String ss = context.getApplicationInfo().nativeLibraryDir;
            if (TextUtils.isEmpty(ss)) {
                ss = "/data/data/" + context.getPackageName() + "/lib/";
            }
            return ss;
        }
        return nativePath;
    }

    protected static String findNativeLibraryPath(Context context, String libraryName) {
        if (context == null) {
            return null;
        }
        if (TextUtils.isEmpty(libraryName)) {
            return null;
        }
        PathClassLoader classLoader = (PathClassLoader) context.getClassLoader();
        return classLoader.findLibrary(libraryName);
    }

    /**
     * 图形转换库的shell指令组合
     *
     * @param prnPath
     * @param imgPath
     * @param colorType
     * @param qualityType
     */
    private static void doCmd(Context context, String prnPath, String imgPath, ColorType colorType, QualityType qualityType) {
        String ct = colorType == ColorType.DOUBLE ? " -t 1 " : " ";
        String qt = qualityType == QualityType.HIGH ? " -m 3 " : "";
        String[] cmds = new String[2];
        String path = getNativePath(context);
//        cmds[0] = "export LD_LIBRARY_PATH=/data/data/" + context.getPackageName() + "/lib:$LD_LIBRARY_PATH";
        cmds[0] = "export LD_LIBRARY_PATH=" + path;
//        cmds[1] = "/data/data/" + context.getPackageName() + "/lib/libimg2inkjet.so" + ct + qt + "--options=\"res=360:unit=1440:num_pins=896:start_doc=1B7801\" -o " + prnPath + " " + imgPath;
        cmds[1] = path + "/libimg2inkjet.so" + ct + qt + "--options=\"res=360:unit=1440:num_pins=896:start_doc=1B7801\" -o " + prnPath + " " + imgPath;
        UsbTool.logd("convertImg-> " + cmds[0] + " " + cmds[1]);
        CommandExecution.execCommand(cmds, false);
    }


    /**
     * 转换图片数据为打印数据
     *
     * @param imgPath
     * @param printParams
     * @return
     */
    public static byte[] convertImg(Context context, String imgPath, PrintParams printParams) {

        ColorType colorType = printParams.colorType;
        QualityType qualityType = printParams.qualityType;
        String prnPath = STOR_PATH + "/a.prn";
        doCmd(context, prnPath, imgPath, colorType, qualityType);
        File file = new File(prnPath);
        byte[] buf = null;
        if (file.exists()) {
            try {
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                buf = new byte[bis.available()];
                bis.read(buf);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            file.delete();
        }
        return buf;
    }

    /**
     * 图形转换库的shell指令组合（双面打印）
     *
     * @param prnPath
     * @param imgPath1
     * @param imgPath2
     * @param colorType
     * @param qualityType
     */
    private static void doCmd(Context context, String prnPath, String imgPath1, String imgPath2, ColorType colorType, QualityType qualityType) {
        String ct = colorType == ColorType.DOUBLE ? " -t 1 " : " ";
        String qt = qualityType == QualityType.HIGH ? " -m 3 " : "";
        String[] cmds = new String[2];
        String path = getNativePath(context);
//        cmds[0] = "export LD_LIBRARY_PATH=/data/data/" + context.getPackageName() + "/lib:$LD_LIBRARY_PATH";
        cmds[0] = "export LD_LIBRARY_PATH="+ path;
//        cmds[1] = "/data/data/" + context.getPackageName() + "/lib/libimg2inkjet.so" + ct + qt + "--options=\"res=360:unit=1440:num_pins=896:start_doc=1B7801:duplex=2\" -o " + prnPath + " " + imgPath1 + " " + imgPath2;
        cmds[1] = path + "/libimg2inkjet.so" + ct + qt + "--options=\"res=360:unit=1440:num_pins=896:start_doc=1B7801:duplex=2\" -o " + prnPath + " " + imgPath1 + " " + imgPath2;
        UsbTool.logd("convertImg-> " + cmds[0] + " " + cmds[1]);
        CommandExecution.execCommand(cmds, false);
    }

    /**
     * 转换图片数据为打印数据（双面）
     *
     * @param imgPath1
     * @param imgPath2
     * @param printParams
     * @return
     */
    public static byte[] convertImg(Context context, String imgPath1, String imgPath2, PrintParams printParams) {
        ColorType colorType = printParams.colorType;
        QualityType qualityType = printParams.qualityType;
        String prnPath = STOR_PATH + "/a.prn";
        doCmd(context, prnPath, imgPath1, imgPath2, colorType, qualityType);
        File file = new File(prnPath);
        byte[] buf = null;
        if (file.exists()) {
            try {
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                buf = new byte[bis.available()];
//                LogUtil.i("buf length:" + buf.length);
                bis.read(buf);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            file.delete();
        }
        return buf;
    }


    public PrintThread printThread;
    public ConvertImgThread convertImgThread;
    public ConvertPdfThread convertPdfThread;

    /**
     * 取消打印pdf任务
     */
    public void cancelPDF() {
        if (convertPdfThread != null)
            convertPdfThread.cancelTask();
        if (convertImgThread != null)
            convertImgThread.cancelTask();
        if (printThread != null)
            printThread.cancelTask();
    }

    /**
     * 打印pdf任务
     *
     * @param pdfPath
     * @param printParams
     * @param printRange  "1,2,3,5-8,10"
     * @param callBack
     */
    public void convertPDF(String pdfPath, PrintParams printParams, String printRange, PDFCallBack callBack) {
        printThread = new PrintThread();
        printThread.setPdfCallBack(callBack);

        convertImgThread = new ConvertImgThread(context);
        convertImgThread.bindPrintThread(printThread);

        convertPdfThread = new ConvertPdfThread(context);
        ConvertPdfThread.PdfTask pdfTask = new ConvertPdfThread.PdfTask();
        pdfTask.pdfPath = pdfPath;
        pdfTask.printParams = printParams;
        pdfTask.printRange = printRange;
        convertPdfThread.setTask(pdfTask);
        convertPdfThread.bindConvertImgThread(convertImgThread);

        convertPdfThread.start();
        convertImgThread.start();
        printThread.start();
    }


//    /**
//     * 打印pdf全流程
//     *
//     * @param pdfPath
//     * @param printParams
//     * @param PrintRange  "1,2,3,5-8,10"
//     * @param callBack
//     */
//    public static void convertPDF(final Context context, final String pdfPath, final PrintParams printParams, String PrintRange, final PDFCallBack callBack) {
//        if (PrintRange == null)
//            return;
//        boolean flag_range = false;
//        final LinkedBlockingDeque<Integer> indexQueue = new LinkedBlockingDeque<Integer>();
//        if (PrintRange != null) {
//            String[] groups = PrintRange.split(",");
//            if (groups != null && groups.length > 0) {
//                for (String str : groups) {
//                    //包含多个字符 如：5-10
//                    if (str.contains("-") && str.indexOf("-") == str.lastIndexOf("-")) {
//                        String[] strings = str.split("-");
//                        int start = Integer.valueOf(strings[0]);
//                        int end = Integer.valueOf(strings[1]);
//                        if (end <= start)
//                            continue;
//                        for (int i = start; i <= end; i++) {
//                            try {
//                                indexQueue.put(i);
//                            } catch (InterruptedException e) {
//                                e.printStackTrace();
//                            }
//                        }
//                        LogUtil.i("index list： " + Arrays.toString(indexQueue.toArray()));
//                    }
//                    //只有单个字符
//                    else if (str.length() == 1) {
//                        int i = Integer.valueOf(str);
//                        try {
//                            indexQueue.put(i);
//                        } catch (InterruptedException e) {
//                            e.printStackTrace();
//                        }
//                    }
//                }
//                if (!indexQueue.isEmpty()) {
//                    flag_range = true;
//                }
//            }
//        }
//
//
//        final SideType sideType = printParams.sideType;
//
//        final HandlerThread print_Thread = new HandlerThread("print thread");
//        print_Thread.start();
//        final Handler printHandler = new Handler(print_Thread.getLooper()) {
//            private boolean result = true;
//
//            @Override
//            public void handleMessage(Message msg) {
//                super.handleMessage(msg);
//                switch (msg.what) {
//                    case 0:
//                        byte[] bytes = (byte[]) msg.obj;
//                        if (callBack != null) {
//                            if (bytes != null) {
//                                LogUtil.i("print thread->打印");
//                                int ret = callBack.onPageConverted(bytes);
//                                LogUtil.i("print thread->打印完成");
//                                if (ret < bytes.length) {
//                                    result = false;
//                                }
//                            } else {
//                                result = false;
//                            }
//                        }
//                        break;
//                    case 1:
//                        LogUtil.i("print thread->打印任务结束");
//                        if (callBack != null) {
//                            if (result)
//                                callBack.onSuccess();
//                            else
//                                callBack.onFail();
//                        }
//                        print_Thread.getLooper().quit();
//                        break;
//                    default:
//                        break;
//                }
//            }
//        };
//
//        final HandlerThread convertTGA_Thread = new HandlerThread("convertTGA thread");
//        convertTGA_Thread.start();
//        final Handler convertTGA_Handler = new Handler(convertTGA_Thread.getLooper()) {
//            @Override
//            public void handleMessage(Message msg) {
//                super.handleMessage(msg);
//                switch (msg.what) {
//                    case 0:
//                        byte[] data = null;
//                        if (sideType == SideType.SINGLE) {
//                            String fileName = (String) msg.obj;
//                            data = convertImg(context, fileName, printParams/*, dpiType*/);
//                            LogUtil.i("convertTGA thread->转换图片到打印数据  " + fileName + " 完成");
//                            File file = new File(fileName);
//                            if (file.exists())
//                                file.delete();
//                        } else if (sideType == SideType.DOUBLE) {
//                            String[] fileNames = (String[]) msg.obj;
//                            if (fileNames[1] != null) {
//                                data = convertImg(context, fileNames[0], fileNames[1], printParams/*, dpiType*/);
//                                LogUtil.i("convertTGA thread->转换图片到打印数据  " + fileNames[0] + "与" + fileNames[1] + " 完成");
//                                for (String name : fileNames) {
//                                    File file = new File(name);
//                                    if (file.exists())
//                                        file.delete();
//                                }
//                            } else {
//                                data = convertImg(context, fileNames[0], printParams/*, dpiType*/);
//                                LogUtil.i("convertTGA thread->转换图片到打印数据  " + fileNames[0] + " 完成");
//                                File file = new File(fileNames[0]);
//                                if (file.exists())
//                                    file.delete();
//                            }
//
//                        }
//                        printHandler.obtainMessage(0, data).sendToTarget();
//
//                        break;
//                    case 1:
//                        LogUtil.i("convertTGA thread->图片转打印数据任务结束");
//                        printHandler.obtainMessage(1).sendToTarget();
//                        convertTGA_Thread.getLooper().quit();
//                        break;
//                    default:
//                        break;
//                }
//            }
//        };
//        final boolean finalFlag_range = flag_range;
//        Thread convertPDF_thread = new Thread(new Runnable() {
//            @Override
//            public void run() {
//                if (finalFlag_range) {
//                    LogUtil.i("convertPDF thread-> 局部转换");
//                    if (sideType == SideType.SINGLE) {
//                        //循环提取队列中的页码，直到所有页码处理完毕
//                        while (!indexQueue.isEmpty()) {
//                            int index = indexQueue.poll();
//                            String ret = pdf2tga(context, pdfPath, index);
//                            //如果页码有效，转换成功则发送
//                            if (ret != null) {
//                                LogUtil.i("convertPDF thread->pdf 第" + index + "页转换tga完成");
//                                convertTGA_Handler.obtainMessage(0, ret).sendToTarget();
//                            }
//                        }
//                        convertTGA_Handler.obtainMessage(1).sendToTarget();
//
//
//                    } else if (sideType == SideType.DOUBLE) {
//                        String[] pair = new String[2];
//                        int pi = 0;
//                        //循环提取队列中的页码，直到所有页码处理完毕
//                        while (!indexQueue.isEmpty()) {
//                            int index = indexQueue.poll();
//                            String ret = pdf2tga(context, pdfPath, index);
//                            //如果页码有效，转换成功
//                            if (ret != null) {
//                                LogUtil.i("convertPDF thread->pdf 第" + index + "页转换tga完成");
//                                //记录转换的图片地址到pair中
//                                pair[pi++] = ret;
//                                //如果pair已经保存有一对图片地址，则发送
//                                if (pi == 2) {
//                                    LogUtil.i("convertPDF thread->pdf 传递一对图片");
//                                    convertTGA_Handler.obtainMessage(0, pair).sendToTarget();
//                                    //重置pair以便下次使用,因为是传递引用给另一个线程，所以只能新建一个pair数组供下次使用
//                                    pi = 0;
//                                    pair = new String[2];
//                                }
//                            }
//                        }
//                        //转换后有效的图片剩余1张不能组合成对
//                        if (pi == 1) {
//                            LogUtil.i("convertPDF thread->pdf 传递剩余1张图片");
//                            convertTGA_Handler.obtainMessage(0, pair).sendToTarget();
//                        }
//                        convertTGA_Handler.obtainMessage(1).sendToTarget();
//
//                    }
//                } else {
//                    LogUtil.i("convertPDF thread-> 全部转换");
//                    if (sideType == SideType.SINGLE) {
//                        int index = 1;
//                        while (true) {
//                            String ret = pdf2tga(context, pdfPath, index);
//                            if (ret == null) {
//                                LogUtil.i("convertPDF thread->pdf转tga任务结束");
//                                convertTGA_Handler.obtainMessage(1).sendToTarget();
//                                break;
//                            } else {
//                                LogUtil.i("convertPDF thread->pdf 第" + index + "页转换tga完成");
//                                convertTGA_Handler.obtainMessage(0, ret).sendToTarget();
//                                index++;
//                            }
//                        }
//                    } else if (sideType == SideType.DOUBLE) {
//                        int index = 1;
//                        String[] pairs = new String[2];
//                        while (true) {
//                            String ret = pdf2tga(context, pdfPath, index);
//                            if (index % 2 == 0) {
//                                if (ret == null) {
//                                    pairs[1] = null;
//                                    LogUtil.i("convertPDF thread->传递剩下的一张图片,pdf转tga任务结束");
//                                    convertTGA_Handler.obtainMessage(0, pairs).sendToTarget();
//                                    convertTGA_Handler.obtainMessage(1).sendToTarget();
//                                    break;
//                                } else {
//                                    pairs[1] = ret;
//                                    LogUtil.i("convertPDF thread->第" + index + "页转换tga完成, 传递一对图片");
//                                    convertTGA_Handler.obtainMessage(0, pairs).sendToTarget();
//                                    //因为数组的引用已经交给转换线程，那么下次必须新建一个数组，并重新指向
//                                    pairs = new String[2];
//                                    index++;
//                                }
//                            } else {
//                                if (ret == null) {
//                                    LogUtil.i("convertPDF thread->pdf转tga任务结束");
//                                    convertTGA_Handler.obtainMessage(1).sendToTarget();
//                                    break;
//                                } else {
//                                    pairs[0] = ret;
//                                    LogUtil.i("convertPDF thread->pdf 第" + index + "页转换tga完成");
//                                    index++;
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//        });
//        convertPDF_thread.start();
//    }

    /**
     * 转换pdf数据为打印数据
     *
     * @param pdfPath
     * @param index
     * @return
     */
    public static String pdf2tga(Context context, String pdfPath, int index, ImgType imgType) {
        String result = null;

        if (pdfPath == null || pdfPath.length() == 0)
            return null;

        String format = ".tga";
        if (imgType == ImgType.TGA) {
            format = ".tga";
        } else if (imgType == ImgType.PNG) {
            format = ".png";
        }

        try {
            // PDF to PNG
//            String pngPath = String.format(STOR_PATH + "/%s-%%d.tga", FILE_NAME);
            String pngPath = String.format(STOR_PATH + "/%s-" + index + format, FILE_NAME);
            final List<String> cmdList = new ArrayList<String>();
//            cmdList.add(getPdfUtilPath(context));//libmudraw.so的路径
            String path = getNativePath(context);
//            cmdList.add("LD_LIBRARY_PATH=" + path);
            cmdList.add(path + "/libmudraw.so");//libmudraw.so的路径
            cmdList.add("-o");
            cmdList.add(pngPath);//将要生成的图片文件路径
            cmdList.add("-w");
            cmdList.add(Integer.toString(2977));//纸张宽度 6000
            cmdList.add("-h");
            cmdList.add(Integer.toString(4208));//纸张高度 8400
            cmdList.add("-T");
            cmdList.add(" 2");//线程
            cmdList.add("-P");
            //cmdList.add("-c");
            //cmdList.add("gray");
            cmdList.add("-s t");//show timings, parameter changed since mupdf 1.7
            cmdList.add(pdfPath);//来源PDF路径
            cmdList.add("" + index);
            UsbTool.logd(cmdList.toString());
            final Process proc;
            ProcessBuilder pb = new ProcessBuilder(cmdList);
            pb.environment().put("LD_LIBRARY_PATH", path);
            proc = pb.start();
            byte[] buf = new byte[1024];
            int a = proc.waitFor();
            if (a != 0) {
                InputStream is = proc.getErrorStream();
                int cnt = is.read(buf);
                if (cnt > 0) {
                    UsbTool.logd("[err]" + new String(buf, 0, cnt));
                }
            } else {
                InputStream is = proc.getErrorStream();// output on stderr since mupdf 1.11
                int cnt = is.read(buf);
                if (cnt > 0) {
                    final String outLines = new String(buf, 0, cnt);
                    UsbTool.logd("outline: " + outLines);
                    ArrayList<String> outFileList = new ArrayList<>();
                    for (String s : outLines.split("\n")) {
//                        LogUtil.i( "out: " + s);
                        // 找到“page”开头的字符串 例如：page /storage/emulated/0/和谐sf欢乐KTV记录.pdf 1 45ms (interpretation) 1474ms (rendering) 1519ms (total)
                        if (s.indexOf("page") == 0) {
//                            LogUtil.i("select:" + s);
//                            //按“ ”划分字符串
//                            String[] parts = s.split(" ");
//                            if (parts != null && parts.length > 0) {
//                                for (int i = 0; i < parts.length; i++) {
//                                    String part = parts[i];
//                                    //找到包含“pdf”的子串，它的后面一个字符串就是页码。
//                                    //由于文件名可能包含空格，所以页码在父字符串的中的位置不固定
//                                    if (part.contains("pdf") && parts.length > i + 1) {
//                                        String ts = parts[i + 1];
//                                        String oname = String.format(STOR_PATH + "/%s-%s.tga", FILE_NAME, ts);
//                                        LogUtil.i( "ret:" + oname);
//                                        outFileList.add(oname);
//                                    }
//                                }
//
//                            }
                            String[] parts = s.split(" ");
                            final String oname = String.format(STOR_PATH + "/%s-%s" + format, FILE_NAME, parts[parts.length - 7]);
                            UsbTool.logd("ret:" + oname);
                            outFileList.add(oname);
                        }
                    }
//                    String flieName = String.format(STOR_PATH + "/%s-" + index + ".tga", FILE_NAME);
                    if (outFileList.size() > 0 && pngPath.equals(outFileList.get(0)))
                        result = outFileList.get(0);
                    else {
                        File file = new File(pngPath);
                        if (file.exists())
                            file.delete();
                    }
                } else {
//                    LogUtil.i("no command line output");
                        /*is = proc.getErrorStream();
                        cnt = is.read(buf);
						if(cnt > 0) {
							Log.d(LOG_TAG, "[err]"+new String(buf, 0, cnt));
							Toast.makeText(this, new String(buf, 0, cnt),
									Toast.LENGTH_SHORT).show();
						}*/
                }
            }
            proc.destroy();
        } catch (IOException e) {
            e.printStackTrace();
            UsbTool.loge(e.getMessage());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return result;
    }


    public enum ColorType {

        SINGLE, DOUBLE
    }

    public enum SideType {
        SINGLE, DOUBLE
    }


    public enum QualityType {
        NORMAL, HIGH
    }

    public enum ImgType {
        TGA, PNG
    }


//    public interface PDFCallBack {
//        int onPageConverted(byte[] pageData);
//
//        void onSuccess();
//
//        void onFail();
//    }


    public static class PrintParams {

        public ColorType colorType;
        public SideType sideType;
        public QualityType qualityType;

        public PrintParams(ColorType colorType, SideType sideType, QualityType qualityType) {
            this.colorType = colorType;
            this.sideType = sideType;
            this.qualityType = qualityType;
        }

        public PrintParams() {
            this.colorType = ColorType.SINGLE;
            this.sideType = SideType.SINGLE;
            this.qualityType = QualityType.NORMAL;
        }

    }

}
